"""Build DAOS components"""

import os

HEADERS = ['daos.h', 'daos_api.h', 'daos_types.h', 'daos_errno.h', 'daos_kv.h',
           'daos_event.h', 'daos_mgmt.h', 'daos_types.h', 'daos_array.h',
           'daos_task.h', 'daos_fs.h', 'daos_uns.h', 'daos_security.h',
           'daos_prop.h', 'daos_obj_class.h', 'daos_obj.h', 'daos_pool.h',
           'daos_cont.h', 'daos_version.h', 'daos_fs_sys.h']
HEADERS_SRV = ['vos.h', 'vos_types.h']
HEADERS_GURT = ['dlog.h', 'debug.h', 'common.h', 'hash.h', 'list.h',
                'heap.h', 'fault_inject.h', 'debug_setup.h',
                'types.h', 'atomic.h', 'slab.h',
                'telemetry_consumer.h', 'telemetry_common.h']

# Keep versioned libs for now to avoid any conflict with 1.0
CART_VERSION = "4.9.0"

def generate_daos_version_header(env):
    """Generate daos_version.h from a template file"""

    tmpl_hdr_in = os.path.join('include', 'daos_version.h.in')
    sd = {'@TMPL_MAJOR@': env['API_VERSION_MAJOR'],
          '@TMPL_MINOR@': env['API_VERSION_MINOR'],
          '@TMPL_FIX@': env['API_VERSION_FIX'],
          '@Template for @' : ""}
    out = env.Substfile(tmpl_hdr_in, SUBST_DICT=sd)
    print("generated daos version header file: {}".format(out[0].abspath))

def scons():
    """Execute build"""

    Import('env', 'base_env', 'prereqs')

    # For Common library (tse.h)
    env.AppendUnique(CPPPATH=[Dir('include/daos').srcnode()])
    env.Install(os.path.join('$PREFIX', 'include/daos'), 'include/daos/tse.h')

    # Detect if we have explicit_bzero
    conf = Configure(env)
    if not conf.CheckFunc('explicit_bzero'):
        env.Append(CCFLAGS=['-DNEED_EXPLICIT_BZERO'])
    conf.Finish()

    # Generic DAOS includes
    env.AppendUnique(CPPPATH=[Dir('include').srcnode()])
    env.AppendUnique(CPPPATH=[Dir('include')])
    base_env.AppendUnique(CPPPATH=[Dir('include').srcnode()])
    base_env.AppendUnique(CPPPATH=[Dir('include')])
    generate_daos_version_header(env)
    for header in HEADERS:
        env.Install(os.path.join('$PREFIX', 'include'), 'include/%s' % header)
    if prereqs.server_requested():
        for header in HEADERS_SRV:
            env.Install(os.path.join('$PREFIX', 'include', 'daos_srv'),
                        'include/daos_srv/%s' % header)
    for header in HEADERS_GURT:
        env.Install(os.path.join('$PREFIX', 'include', 'gurt'),
                    'include/gurt/%s' % header)

    env.Append(CCFLAGS=['-DCART_VERSION=\\"' + CART_VERSION + '\\"'])
    env.AppendUnique(CPPPATH=[Dir('cart/test/utest').srcnode()])
    Export('env', 'CART_VERSION')

    SConscript('gurt/SConscript')
    SConscript('cart/SConscript')
    Default('gurt')
    # Generate the common libraries used by more than one component
    SConscript('common/SConscript')
    SConscript('bio/SConscript')
    SConscript('vea/SConscript')
    SConscript('vos/SConscript')

    # Build each DAOS component
    SConscript('rsvc/SConscript')
    SConscript('mgmt/SConscript')
    SConscript('pool/SConscript')
    SConscript('container/SConscript')
    SConscript('placement/SConscript')
    SConscript('dtx/SConscript')
    SConscript('object/SConscript')
    SConscript('rebuild/SConscript')
    SConscript('security/SConscript')

    # Build cart utilities library
    SConscript('cart/utils/SConscript')

    # Build DAOS client libraries
    SConscript('client/SConscript')

    # rdb unit test rdbt depends on libdaos
    SConscript('rdb/SConscript')

    # Then the DAOS I/O Engine executable
    SConscript('engine/SConscript')

    # Build utilities
    SConscript('utils/SConscript')

    # Build the control plane components
    SConscript('control/SConscript')

    # Build test
    SConscript('tests/SConscript')

    if not env.GetOption('clean') and not env.GetOption('help'):

        print("Checking local headers can be included")
        broken_includes = False
        config_env = env.Clone()
        config = Configure(config_env)
        for header in HEADERS_GURT:
            if not config.CheckHeader(os.path.join('gurt', header)):
                broken_includes = True
        config.Finish()

        if broken_includes:
            print("Broken local header files, cannot continue")
            Exit(2)

if __name__ == "SCons.Script":
    scons()
